Uso de la interfaz de scripting de Git
CODESYS Git proporciona una interfaz de scripting para Git. A continuación se muestran ejemplos de cómo usar la interfaz. A continuación también encontrarás información sobre la salida en texto de los mensajes generados por muchas operaciones de Git
Para más información, ver: Documentación de la API del motor de secuencias de comandos
Requerimientos
Para ejecutar los ejemplos siguientes, es necesario lo siguiente:
CODESYS 3.5.19.30 o superior
También se requieren los siguientes componentes:
CODESYS Library Documentation Support (para crear la biblioteca compilada)
CODESYS Git 1.6.0.0 o superior
Una instalación local de Git
Importante
Utilice contraseñas de SecureString siempre que sea posible
Para aumentar la seguridad, las contraseñas deben pasarse como SecureString de.NET.
Las operaciones de GIT afectadas son: clone
, fetch
, pull
, push
SecureStrings se puede crear en IronPython de la siguiente manera. La «contraseña» en sí misma debe provenir de una cadena segura y no, como aquí se muestra a modo de demostración, estar en texto plano en el script. Internamente, cada contraseña proporcionada se maneja de forma segura
from System.Security import SecureString sec_str_password = SecureString() for c in "Passwort": sec_str_password.AppendChar(c)
Para más medidas de seguridad al usar CODESYS Git consulte: Seguridad para CODESYS Git
Preparación
CODESYS biblioteca
Porque no CODESYS las bibliotecas se administran actualmente en Git, las fuentes de un CODESYS la biblioteca es obligatoria. String Functions.library
biblioteca del CODESYS String Libraries el producto se usa en los ejemplos.
Repositorio remoto de Git
Para este ejemplo, se usa un repositorio Git simple en el sistema de archivos como repositorio remoto.
Para prepararlo, primero borre el directorio correspondiente y, a continuación, cree uno nuevo.
import shutil import os def prepare_empty_dir(empty_dir_path): print("Prepare empty directory at", empty_dir_path) shutil.rmtree(empty_dir_path, ignore_errors=True) if not(os.path.exists(empty_dir_path) and os.path.isdir(empty_dir_path)): os.makedirs(empty_dir_path)
A continuación, se crea un repositorio Git vacío.
import subprocess def create_bare_git_repository(bare_repository_path): print("Create bare git repository at", bare_repository_path) create_bare_repository_cmd = 'cmd /c "git -C \"' + bare_repository_path + '\" init --bare"' try: retcode = subprocess.call(create_bare_repository_cmd, shell=True) if retcode < 0: raise Exception("Creating bare git repository at " + bare_repository_path + " failed: ", -retcode) else: print("Creating bare git repository at " + bare_repository_path + " succeeded.") except Exception as e: print("[ERROR] Creating bare git repository failed: ", e) raise
El repositorio vacío de Git se llena con el contenido del CODESYS biblioteca.
def initialize_bare_git_repository(library_path, local_repository_path, bare_repository_path): print("Open library:", library_path) project = projects.open(library_path) print("Initiate local git repository") project.git.init(local_repository_path) project.git.commit_complete("Create git repo for lib", "user", "mail@mail") print("Push to remote git repository") origin_remote = project.git.remote_add("origin", bare_repository_path) project.git.branch_set_upstream_to(origin_remote) project.git.push() project.git.de_init(cleanUpFileSystem=True) project.close()
El siguiente script ejecuta las funciones descritas.
import os def main(): if projects.primary: projects.primary.close() basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\" project_basepath = os.path.join(basepath, "projects\\") library_file_name = "ExampleLib1.library" library_path = os.path.join(project_basepath, library_file_name) remote_repo_basepath = os.path.join(basepath, "remotes\\") remote_repo_directory_name = "ExampleLib1RemoteRepo" remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name) local_repo_basepath = os.path.join(basepath, "repos\\") local_repo_directory_name = "ExampleLib1LocalRepo" local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name) print("Create and push library to remote git repository") prepare_empty_dir(remote_repo_path) create_bare_git_repository(remote_repo_path) initialize_bare_git_repository(library_path, local_repo_path, remote_repo_path) print("[Success] All done") if __name__ == '__main__': main()
El repositorio Git simple creado de esta manera y provisto de contenido se usa para los demás ejemplos.
Clonación de un repositorio Git remoto
Se ejecuta la siguiente función git clone
para un repositorio Git remoto.
def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path): update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags) project.save() return project
Creación y fusión de una nueva sucursal
La siguiente función auxiliar crea algunos objetos nuevos en un CODESYS proyecto como ejemplo.
def add_dut(project): ST_STRUCT_STR = """\ a : BOOL; b : BIT; c : BIT; """ ST_UNION_STR = """\ TYPE ExampleUnion : UNION Zahl : INT; Prozent : ExampleAlias; Bits : ExampleStruct; END_UNION END_TYPE """ # Create a struct DUT and insert the list of variables just into the right # place in line two, row 0 (line numbering starts with line 0) example_dut_struct = project.create_dut('ExampleStruct') # DutType.Structure is the default example_dut_struct.textual_declaration.insert(2, 0, ST_STRUCT_STR) # Alias types get their "content" via the base type, which will just end up # as one line in the declaration part: # TYPE MyAlias : INT (0..100); END_TYPE example_dut_alias = project.create_dut('ExampleAlias', DutType.Alias, "INT (0..100)") # Instead of injecting the variables into the existing declaration, # one can also just replace the complete declaration part, including the # boilerplate code. example_dut_union = project.create_dut('ExampleUnion', DutType.Union) example_dut_union.textual_declaration.replace(ST_UNION_STR)
La siguiente función auxiliar incrementa la versión de compilación en la información del proyecto de un CODESYS proyecto.
def increment_build_version(project): """ Increment build version in project info. """ info = project.get_project_info() old_version = info.version info.version = (old_version.Major, old_version.Minor, old_version.Build + 1, 0) project.save()
La siguiente función crea primero una nueva rama y realiza cambios en esta rama y, a continuación, combina estos cambios de nuevo en la rama principal.
def copy_branch_and_merge(project): current_branch = project.git.branch_show_current() print("Current branch: ", current_branch.friendly_name) project, current_branch = project.git.branch_copy(current_branch, "new_branch", checkout=True) print("Current branch: ", current_branch.friendly_name) add_dut(project) project.git.commit_complete("Added DUT", "user", "mail@mail") increment_build_version(project) project.git.commit_complete("Incremented build version", "user", "mail@mail") project, current_branch = project.git.checkout("master") print("Current branch: ", current_branch.friendly_name) project, merge_result = project.git.merge("new_branch") print("Merged: ", merge_result.ToString()) project.save() return project
Se ejecuta el siguiente script git clone
para un repositorio Git remoto, realiza cambios en el proyecto y, a continuación, los envía al repositorio Git remoto (CopyBranchAndMerge.py).
def main(): if projects.primary: projects.primary.close() basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\" project_basepath = os.path.join(basepath, "projects\\") library_file_name = "ExampleLib1Cloned.library" remote_repo_basepath = os.path.join(basepath, "remotes\\") remote_repo_directory_name = "ExampleLib1RemoteRepo" remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name) local_repo_basepath = os.path.join(basepath, "repos\\") local_repo_directory_name = "ExampleLib1LocalRepo" local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name) print("Clone project") project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path) project = copy_branch_and_merge(project) project.git.push() project.save() project.git.de_init(cleanUpFileSystem=True) project.save() project.close() print("[Success] All done") if __name__ == '__main__': main())
Creación de una biblioteca compilada
Se ejecuta el siguiente script git clone
para un CODESYS biblioteca fuente desde un repositorio Git remoto y, a continuación, crea una biblioteca compilada a partir de ella (CreateCompiledLibrary.py).
import os class CompileError(Exception): pass def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path): update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags) project.save() return project def create_compiled_library(project): # requires the CODESYS Library Documentation Support Package! project.check_all_pool_objects() compile_result_message = system.get_messages(category='{97F48D64-A2A3-4856-B640-75C046E37EA9}')[-1] if "0 errors" in compile_result_message: project.save_as_compiled_library(destination_name=None) else: raise CompileError("Compile failed: " + compile_result_message) return project basepath = "D:\\JiraTickets\\GIT-145\\" project_basepath = os.path.join(basepath, "projects\\") remote_repo_basepath = os.path.join(basepath, "remotes\\") remote_repo_directory_name = "StringFunctions.git" remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name) local_repo_basepath = os.path.join(basepath, "repos\\") local_repo_path = os.path.join(local_repo_basepath, "StringFunctions.git") print("Clone project") project = clone_git_repository(project_basepath, "String Functions Cloned.library", remote_repo_path, local_repo_path) project = create_compiled_library(project) project.git.de_init(cleanUpFileSystem=True) project.close() print("[Success] All done")
Instalación de una biblioteca desde un repositorio remoto de Git
Se ejecuta el siguiente script git clone
para un CODESYS biblioteca fuente desde un repositorio Git remoto e instala esta biblioteca en el repositorio actual CODESYS instancia (InstallLibrary.py).
import os def clone_git_repository(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path): update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode project = git.clone(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags) project.save() return project def install_library(project): library_repo = librarymanager.repositories[0] librarymanager.install_library(project.path, library_repo, True) def main(): if projects.primary: projects.primary.close() basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\" project_basepath = os.path.join(basepath, "projects\\") library_file_name = "ExampleLib1Cloned2.library" remote_repo_basepath = os.path.join(basepath, "remotes\\") remote_repo_directory_name = "ExampleLib1RemoteRepo" remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name) local_repo_basepath = os.path.join(basepath, "repos\\") local_repo_directory_name = "ExampleLib1LocalRepo" local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name) print("Clone project") project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path) print("Install library") install_library(project) project.git.de_init(cleanUpFileSystem=True) project.close() print("[Success] All done") if __name__ == '__main__': main()
Salida de mensajes para operaciones de Git
Cuando se usa CODESYS Git, la mayoría de los comandos proporcionan resultados basados en texto. Cuando se ejecuta CODESYS en la línea de comandos, se genera automáticamente durante la ejecución de CODESYS Git comandos a través del controlador de script. Cuando se usa CODESYS Git en CODESYS Development System, las salidas también aparecen en la ventana de mensajes.
Structure of the messages: Git:<severity>: [<time>] <text>
In the user interface of CODESYS Git, the output is reduced to: [<time>] <text>
severity
: categoría de mensaje. Las categorías van desde las puramente informativas hasta las de error críticotime
: Hora exacta del mensaje. Formato:HH:MM:SS
text
: Contenido del mensaje. En el caso de los comandos estándar de Git, el contenido corresponde al comando de la línea de comandos que arrojaría el mismo resultado que la llamada realizada al controlador del script. CODESYS Git comandos que no corresponden a un comando estándar de Git (por ejemplo, Recuperar el proyecto del repositorio), el texto del mensaje explica la acción realizada.
Commands with multiple messages:
Para algunos comandos (por ejemplo, git log
), la salida se divide en varios mensajes. En el caso de git log
, cada confirmación que se muestra se muestra en un mensaje separado. En este caso, para dejar claro que estos mensajes forman parte del git log
comando, se hace referencia al comando original en los mensajes.